package cn.fintecher.pangolin.service.report.task;

import cn.fintecher.pangolin.common.enums.BaseSelect;
import cn.fintecher.pangolin.common.enums.PayCheckStatus;
import cn.fintecher.pangolin.common.utils.ZWDateUtil;
import cn.fintecher.pangolin.entity.elastic.BaseCase;
import cn.fintecher.pangolin.entity.elastic.CaseTransferLog;
import cn.fintecher.pangolin.entity.elastic.HistoryCases;
import cn.fintecher.pangolin.entity.elastic.UserPayment;
import cn.fintecher.pangolin.entity.mysql.*;
import cn.fintecher.pangolin.service.report.elastic.BaseCaseElastic;
import cn.fintecher.pangolin.service.report.elastic.CaseTransferLogElastic;
import cn.fintecher.pangolin.service.report.elastic.HistoryCasesElastic;
import cn.fintecher.pangolin.service.report.repository.CaseInfoRepository;
import cn.fintecher.pangolin.service.report.repository.PaymentCheckRepository;
import com.querydsl.core.BooleanBuilder;
import org.apache.commons.collections4.IterableUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @Auther: xiaqun
 * @Description:
 * @Date: 11:16 2019/12/16
 */

@Service("userPaymentTask")
public class UserPaymentTask {
    @Autowired
    private CaseTransferLogElastic caseTransferLogElastic;

    @Autowired
    private CaseInfoRepository caseInfoRepository;

    @Autowired
    private BaseCaseElastic baseCaseElastic;

    @Autowired
    private HistoryCasesElastic historyCasesElastic;

    @Autowired
    private PaymentCheckRepository paymentCheckRepository;

    /**
     * 生成催收员回款历史数据
     */
    @Async
    public CompletableFuture<UserPayment> doTask(User user, Date date) {
        DateTime dateTime = new DateTime(date);
        Date endDate = dateTime.plusDays(1).toDate();
        UserPayment userPayment = new UserPayment();
        userPayment.setId(UUID.randomUUID().toString().replaceAll("-", "")); //主键ID
        userPayment.setDepartId(user.getDepartment().getId()); //部门ID
        userPayment.setDepartName(user.getDepartment().getName()); //部门名称
        userPayment.setDepartCode(user.getDepartment().getDepartCode()); //部门code
        userPayment.setReportDate(date); //报表统计时间
        userPayment.setUserId(user.getId()); //用户ID
        userPayment.setUserName(user.getRealName()); //用户名称
        //统计在催的案件
        Iterable<CaseInfo> caseInfoIterable = caseInfoRepository.findAll(QCaseInfo.caseInfo.currentCollector.id.eq(user.getId()));
        List<CaseInfo> caseInfoList = IterableUtils.toList(caseInfoIterable);
        double amt = 0d;
        int num = caseInfoList.size();
        for (CaseInfo caseInfo : caseInfoList) {
            amt += caseInfo.getLeftAmt();
        }
        //统计流出的案件
        BoolQueryBuilder builder = new BoolQueryBuilder();
        builder.must(QueryBuilders.matchPhraseQuery("outUserId.keyword", user.getId()));
        builder.must(QueryBuilders.rangeQuery("operatorTime").gte(date.getTime()));
        builder.must(QueryBuilders.rangeQuery("operatorTime").lt(endDate.getTime()));
        Iterable<CaseTransferLog> caseTransferLogIterable = caseTransferLogElastic.search(builder);
        List<CaseTransferLog> caseTransferLogs = IterableUtils.toList(caseTransferLogIterable);
        int outCaseNum = 0;
        if (!caseTransferLogs.isEmpty()) {
            Map<String, List<CaseTransferLog>> map = caseTransferLogs.stream().collect(Collectors.groupingBy(CaseTransferLog::getCaseId));
            List<String> caseIds = new ArrayList<>();
            for (Map.Entry<String, List<CaseTransferLog>> entry : map.entrySet()) {
                boolean flag = false;
                for (CaseInfo caseInfo : caseInfoList) {
                    if (entry.getKey().equals(caseInfo.getId())) {
                        flag = true;
                        break;
                    }
                }
                if (!flag) {
                    caseIds.add(entry.getKey());
                    outCaseNum++;
                }
            }
            builder = new BoolQueryBuilder();
            builder.must(QueryBuilders.termsQuery("id.keyword", caseIds));
            Iterable<BaseCase> baseCaseIterable = baseCaseElastic.search(builder);
            List<BaseCase> baseCaseList = IterableUtils.toList(baseCaseIterable);
            for (BaseCase baseCase : baseCaseList) {
                amt += baseCase.getLeftAmt();
            }
            Iterable<HistoryCases> historyCasesIterable = historyCasesElastic.search(builder);
            List<HistoryCases> historyCasesList = IterableUtils.toList(historyCasesIterable);

            for (HistoryCases historyCases : historyCasesList) {
                amt += historyCases.getLeftAmt();
            }
        }
        userPayment.setCollectingNumber(num + outCaseNum); //在催案件数
        userPayment.setCollectingAmt(amt); //在催案件金额

        BooleanBuilder booleanBuilder = new BooleanBuilder();
        QPaymentCheck qPaymentCheck = QPaymentCheck.paymentCheck;
        booleanBuilder.and(qPaymentCheck.payCheckStatus.eq(PayCheckStatus.CP)).and(qPaymentCheck.isReply.eq(BaseSelect.YES).and(qPaymentCheck.applyId.eq(user.getId())));
        booleanBuilder.and(qPaymentCheck.hasPaymentDate.goe(date)).and(qPaymentCheck.hasPaymentDate.loe(ZWDateUtil.getNowDateTime()));
        Iterable<PaymentCheck> paymentCheckIterable = paymentCheckRepository.findAll(booleanBuilder);
        List<PaymentCheck> paymentChecks = IterableUtils.toList(paymentCheckIterable);
        int paymentNum = 0;
        double paymentAmt = 0d;
        for (PaymentCheck paymentCheck : paymentChecks) {
            paymentNum++;
            paymentAmt += paymentCheck.getHasPaymentAmt();
        }
        userPayment.setPaymentNumber(paymentNum); //回款笔数
        userPayment.setPaymentAmt(paymentAmt); //回款金额
        if (amt == 0d) {
            userPayment.setPaymentRate(0f); //回款率
        } else {
            userPayment.setPaymentRate(new BigDecimal(paymentAmt / amt).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue()); //回款率
        }
        return CompletableFuture.completedFuture(userPayment);
    }
}
